package com.sec.dao.mysql.impl;

import com.sec.dao.mysql.BaseDao;
import com.sec.hibernate.CustomerContextHolder;
import com.sec.util.GenericsUtils;
import com.sec.util.Pager;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Query;
import org.hibernate.Transaction;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Repository
@Transactional
public class BaseDaoImpl<T> implements BaseDao<T> {

    @Resource
    private SessionFactory sessionFactory;
    private Class<T> clazz;

    @Override
    public Session getSession() {
        CustomerContextHolder.setCustomerType(CustomerContextHolder.SESSION_FACTORY_SQLSERVER);
        return sessionFactory.getCurrentSession();
    }

    @Override
    public void save(T entity) {
        getSession().save(entity);
        getSession().flush();
    }

    @Override
    public void delete(T entity) {
        getSession().delete(entity);
        getSession().flush();
    }

    @Override
    public void update(T entity) {
        getSession().update(entity);
        getSession().flush();
    }

    @Override
    public T queryById(Serializable id) {
        if (id == null) {
            return null;
        } else {
            return (T) getSession().get(clazz, id);
        }
    }

    @Override
    public List<T> queryAll() {
        return getSession().createQuery("FROM " + clazz.getSimpleName()).list();
    }

    @Override
    public List<T> queryListByHql(String queryString, Object... values) {
        Query queryObject = getSession().createQuery(queryString);
        if (values != null && values.length > 0) {
            for (int i = 0; i < values.length; i++) {
                queryObject.setParameter(i, values[i]);
            }
        }
        return queryObject.list();
    }

    @Override
    public List<T> queryByCon(T entity) {
        String query_sql = "";
        // 组织查询语句
        // 获取对象所有的字段
        Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        String[] fieldNames = getFiledName(entityClass);
        boolean field_null = true;
        for (String fieldName : fieldNames) {
            Object value = getFieldValueByName(fieldName, entity);
            if (value != null && !value.equals("")) {
                if (fieldName.contains("id") && value.toString().equals("0")) { // 如果是id相关且结果为0，不加入hql

                } else {
                    field_null = false;
                    query_sql += " AND " + fieldName + " = :" + fieldName;
                }
            }
        }
        Query query;
        if (field_null) {
            query = getSession().createQuery("from " + entityClass.getName());
        } else {
            query = getSession().createQuery("from " + entityClass.getName() + " WHERE 1=1" + query_sql);
            for (String fieldName : fieldNames) {
                Object value = getFieldValueByName(fieldName, entity);
                if (value != null && !value.equals("")) {
                    if (fieldName.contains("id") && value.toString().equals("0")) { // 如果是id相关且结果为0，不加入hql
                    } else {
                        query.setParameter(fieldName, value);
                    }
                }
            }
        }

        List<T> list = query.list();
        getSession().flush();
        if (list != null && list.size() != 0) {
            return list;
        } else {
            return new ArrayList<>();
        }
    }

    @Override
    // 分页查询
    public Pager pagerff(Pager p, Map<String, Object> pram) {
        Session session = null;
        session = getSession();
        String hql = p.getHql();//获取查询语句
        Query query = session.createQuery(hql).setCacheable(true);
        //设置参数
        query.setProperties(pram);
        //查询具体数据
        int count = query.list().size();
        p.setRowsTotal(count);
        int nowPage = 1;
        if (p.getPage() > 0) {
            nowPage = p.getPage();
        }
        //指定从那个对象开始查询，参数的索引位置是从0开始的，
        query.setFirstResult((p.getPage() - 1) * p.getRows());
        //分页时，一次最多产寻的对象数
        query.setMaxResults(p.getRows());
        List<?> list1 = query.list();
        p.setList(list1);

        return p;
    }




    /**
     * 该类初始化时通过反射机制获取T的真实类型
     */
    public BaseDaoImpl() {
        // 获取当前new的对象的泛型的父类类型
        //ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        // 获取第一个类型参数的真实类型
        //this.clazz = (Class<T>) pt.getActualTypeArguments()[0];
        this.clazz = GenericsUtils.getSuperClassGenricType(this.getClass(), 0);
    }

    /**
     * 获取属性名数组
     */
    private String[] getFiledName(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        String[] fieldNames = new String[fields.length];
        for (int i = 0; i < fields.length; i++) {
            fieldNames[i] = fields[i].getName();
        }
        return fieldNames;
    }

    /**
     * 根据属性名获取属性值
     */
    private Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(o, new Object[]{});
            return value;
        } catch (Exception e) {
            return null;
        }
    }


}
